package com.asen.libcommon.widget.input

import android.content.Context
import android.text.*
import android.text.InputFilter.LengthFilter
import android.util.AttributeSet
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
import androidx.appcompat.widget.AppCompatEditText
import java.util.*
import java.util.regex.Pattern

/**
 * @author : asenLiang
 * @date   : 2020/12/24
 * @e-mail : liangAisiSen@163.com
 * @desc   : 输入框封装（最大值、最小值、手机号、整数、精确输入到第几位小数点）
 */
class XEditText : AppCompatEditText {
    // 保存设置的所有输入限制
    private var inputFilters: MutableList<InputFilter> = ArrayList()

    fun getInputFilters():MutableList<InputFilter> = inputFilters

    constructor(context: Context?) : super(context!!)

    constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs)

    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context!!,
        attrs,
        defStyleAttr
    )

    /** 设置允许输入的最大字符数 */
    fun setMaxLengthFilter(maxLength: Int) {
        inputFilters.add(LengthFilter(maxLength))
        filters = inputFilters!!.toTypedArray()
    }

    /** 设置可输入小数位 */
    fun setDecimalFilter(num: Int) {
        inputFilters.add(SignedDecimalFilter(0, num))
        filters = inputFilters!!.toTypedArray()
    }

    /**
     * 设置最大值
     * @param maxmum       允许的最大值
     * @param numOfDecimal 允许的小数位
     */
    fun setMaxmumFilter(maxmum: Double, numOfDecimal: Int, maxHintCallback: (()->Unit)? = null) {
        inputFilters.add(MaxmumFilter(0, maxmum, numOfDecimal, maxHintCallback = maxHintCallback))
        filters = inputFilters!!.toTypedArray()
    }

    /**
     * 设置只能输入整数
     * @param min 输入整数的最小值
     */
    fun setIntergerFilter(min: Int) {
        inputFilters.add(SignedIntegerFilter(min))
        filters = inputFilters!!.toTypedArray()
    }

    /** 只能够输入手机号码 */
    fun setTelFilter() {
        inputFilters.add(TelephoneNumberInputFilter())
        filters = inputFilters!!.toTypedArray()
    }

    /** 限制只能输入中文 和中文标点符号 ； isPureChinese = true的时候只有中文字*/
    fun setChineseInputFilter(isPureChinese: Boolean = false,hintCallback: (()->Unit)? = null) {
        inputFilters.add(ChineseInputFilter(isPureChinese,hintCallback))
        filters = inputFilters!!.toTypedArray()
    }

    /** 小数位数限制 */
    private class SignedDecimalFilter internal constructor(
        min: Int,
        numOfDecimals: Int,
        private val pattern: Pattern = Pattern.compile("^" + (if (min < 0) "-?" else "") + "[0-9]*\\.?[0-9]" + if (numOfDecimals > 0) "{0,$numOfDecimals}$" else "*")
    ) : InputFilter {
        override fun filter(
            source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int
        ): CharSequence {
            if (source == ".") {
                if (dstart == 0 || dest[dstart - 1] !in '0'..'9' || dest[0] == '0') return ""
            }
            //防止在369.369的最前面输入0变成0369.369这种不合法的形式
            if (source == "0" && dest.toString().contains(".") && dstart == 0) return ""

            val builder = StringBuilder(dest)
            builder.delete(dstart, dend)
            builder.insert(dstart, source)
            return if (!pattern.matcher(builder.toString()).matches()) "" else source
        }
    }

    /** 限制输入最大值 */
    private class MaxmumFilter internal constructor(
        min: Int,
        private val maxNum: Double,
        numOfDecimals: Int,
        private val pattern: Pattern = Pattern.compile("^" + (if (min < 0) "-?" else "") + "[0-9]*\\.?[0-9]" + if (numOfDecimals > 0) "{0,$numOfDecimals}$" else "*"),
        private val maxHintCallback: (()->Unit)? = null
    ) : InputFilter {

        override fun filter(
            source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int
        ): CharSequence {
            if (source == ".") {
                if (dstart == 0 || dest[dstart - 1] !in '0'..'9' || dest[0] == '0') return ""
            }
            if (source == "0" && dest.toString().contains(".") && dstart == 0) return ""

            val builder = StringBuilder(dest)
            builder.delete(dstart, dend)
            builder.insert(dstart, source)
            if (!pattern.matcher(builder.toString()).matches()) return ""

            if (!TextUtils.isEmpty(builder)) {
                val num = builder.toString().toDouble()
                if (num > maxNum) {
                    maxHintCallback?.invoke()
                    return ""
                }
            }
            return source
        }
    }

    /** 限制整数 */
    private class SignedIntegerFilter internal constructor(
        private val min: Int,
        private val pattern: Pattern = Pattern.compile("^" + (if (min < 0) "-?" else "") + "[0-9]*$")
    ) : InputFilter {
        override fun filter(
            source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int
        ): CharSequence {
            // 控制不能全部输入0
            if (min >= 0 && !dest.isNullOrEmpty() && dest.length == 1 && dest.toString()
                    .toInt() == 0 && !source.isNullOrEmpty() && source.toString().toInt() == 0
            ) return ""
            val builder = StringBuilder(dest)
            builder.insert(dstart, source)
            return if (!pattern.matcher(builder.toString()).matches()) "" else source
        }
    }

    /** 限制电话号码 */
    private class TelephoneNumberInputFilter : InputFilter {
        override fun filter(
            source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int
        ): CharSequence {
            val builder = StringBuilder(dest)
            builder.insert(dstart, source)
            val length = builder.length
            if (length == 1) return if (builder[0] == '1') source else ""

            if (length in 1..11) {
                val suffixSize = length - 2
                val pattern = Pattern.compile("^1[3-9]\\d{$suffixSize}$")
                return if (pattern.matcher(builder.toString()).matches()) source else ""
            }
            return ""
        }
    }

    /** 限制只能输入中文 */
    private class ChineseInputFilter internal constructor(
        private var isPureChinese: Boolean = false, // 是否纯中文
        private var hintCallback: (()->Unit)? = null
    ) : InputFilter {
        override fun filter(
            source: CharSequence, start: Int, end: Int, dest: Spanned, dstart: Int, dend: Int
        ): CharSequence {

            if (!source.isNullOrEmpty()) {

                if (isPureChinese) {
                    // [^a-zA-Z0-9\u4E00-\u9FA5]
                    val p = Pattern.compile("^[\\u4e00-\\u9fa5]{0,}\$")
                    val m = p.matcher(source)
                    if (m.matches()) return source else {
                        hintCallback?.invoke()
                    }
                } else {
                    if (isChinese(source[0])) return source else {
                        hintCallback?.invoke()
                    }
                }

            }

            return ""
        }

        /** 可输入中文标点符号 */
        private fun isChinese(source: Char): Boolean {
            val ub = Character.UnicodeBlock.of(source)
            // 4E00-9FBF：CJK 统一表意符号
            if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                //F900-FAFF：CJK 兼容象形文字
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                //3400-4DBF：CJK 统一表意符号扩展 A
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                //2000-206F：常用标点
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                //3000-303F：CJK 符号和标点
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                //FF00-FFEF：半角及全角形式
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
            ) {
                return true
            }
            return false
        }

    }

    /** 监听文本输入 */
    fun onTextChanged(
        afterTextChanged: ((s: Editable?) -> Unit)? = null,
        beforeTextChanged: ((s: CharSequence?, start: Int, count: Int, after: Int) -> Unit)? = null,
        onTextChanged: ((s: CharSequence?, start: Int, before: Int, count: Int) -> Unit)? = null
    ) {
        addTextChangedListener(object : TextWatcher {
            override fun afterTextChanged(s: Editable?) {
                afterTextChanged?.invoke(s)
            }

            override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
                beforeTextChanged?.invoke(s, start, count, after)
            }

            override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
                onTextChanged?.invoke(s, start, before, count)
            }

        })
    }

    /** 显示输入框 */
    fun showKeyboard() {
        requestFocus()
        val inputManager =
            context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        inputManager.showSoftInput(this, 0)
    }

    /** 隐藏输入框 */
    fun hideKeyboard() {
        val imm = context?.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
        clearFocus()
        imm.hideSoftInputFromWindow(windowToken, 0)
    }
}



// todo：输入框的长度限制
fun EditText.extSetLengthFilter(list:MutableList<InputFilter>, maxLen:Int){
    var isExistence = 0 // 计算是否存在长度显示条件
    list.mapIndexed { index, inputFilter ->
        // 获取长度限制条件进行替换长度
        if (inputFilter is LengthFilter){
            isExistence++
            list[index] = LengthFilter(maxLen)
        }
    }

    if (isExistence == 0){
        list.add(LengthFilter(maxLen))
    }

    filters = list.toTypedArray()

}